/**
 * AbstractLego4jMethodInterceptor.java
 * 
 * Created on Jul 10, 2008 at 8:03:20 PM
 */
package org.lego4j;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.concurrent.ConcurrentHashMap;

import org.aopalliance.intercept.MethodInterceptor;

/**
 * TODO add javadoc to AbstractLego4jMethodInterceptor
 *
 * @author <a href="alexguev@gmail.com">Alexei Guevara</>
 * @version $Revision:$ updated on $Date:$ by $Author:$
 */
public abstract class AbstractLego4jMethodInterceptor<P, A extends Annotation> implements MethodInterceptor {
    
    private final Class<A> myAnnotationClass;
    private final ConcurrentHashMap<Method, P> myPolicyCache;

    protected AbstractLego4jMethodInterceptor( Class<A> theAnnotationClass ) {
        myAnnotationClass = theAnnotationClass;
        myPolicyCache = new ConcurrentHashMap<Method, P>( );
    }
    
    protected P createUniquePolicyForMethod( Method theMethod ) {
        P policy = myPolicyCache.get( theMethod );
        if (policy==null) {
            policy = createPolicy( extractAnnotation( theMethod ) );
            //maybe another thread added a strategy right b4 the current one
            P existingPolicy = myPolicyCache.putIfAbsent( theMethod, policy );
            if (existingPolicy!=null) {
                policy = existingPolicy; 
            }
        }
        return policy;
    }

    private A extractAnnotation(Method theMethod) {
        return theMethod.getAnnotation( myAnnotationClass );
    }

    protected abstract P createPolicy( A theAnnotation );

}
